package com.kongjs.application.config;


import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.JWSVerificationKeySelector;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
import com.nimbusds.jwt.proc.DefaultJWTProcessor;
import com.nimbusds.jwt.proc.JWTProcessor;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
@EnableAspectJAutoProxy
@Configuration
public class JwtConfig {
    @Resource
    private JwtProperties jwtProperties;

    private JWTProcessor<SecurityContext> processor() {
        Set<JWSAlgorithm> jwsAlgorithms = new HashSet<>();
        jwsAlgorithms.add(JWSAlgorithm.ES512);
        String jwkContent;
        try {
            jwkContent = jwtProperties.getAccessTokenPublicKey().getContentAsString(StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException("加载jwt公钥失败", e);
        }
        JWK jwk;
        try {
            jwk = JWK.parse(jwkContent);
        } catch (ParseException e) {
            throw new RuntimeException("解析jwt公钥失败", e);
        }
        JWKSource<SecurityContext> jwkSource = new ImmutableJWKSet<>(new JWKSet(jwk));
        JWSVerificationKeySelector<SecurityContext> jwsVerificationKeySelector = new JWSVerificationKeySelector<>(jwsAlgorithms, jwkSource);
        ConfigurableJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
        jwtProcessor.setJWSKeySelector(jwsVerificationKeySelector);
        jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {
        });
        return jwtProcessor;
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(processor());
        OAuth2TokenValidator<Jwt> withClockSkew = new DelegatingOAuth2TokenValidator<>(
                new JwtTimestampValidator(jwtProperties.getClockSkew())
        );
        jwtDecoder.setJwtValidator(withClockSkew);
        return jwtDecoder;
    }
}
